package com.gopay.checkorder.service.task;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.service.task.thread.CheckOrderTaskThread;
import com.gopay.common.cps.manager.bank.BankOrderQueryManager;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.util.ExecutorUtil;

/**
 * 对单Task
 * 
 * @CheckOrderTask.java
 * @author liujy
 * @2013-3-21 上午10:54:27 www.gopay.com.cn Inc.All rights reserved.
 */
public class CheckBcdlOrderTaskImpl implements Task {

	private final static Logger logger = LoggerFactory.getLogger("CHECK_ORDER");
	
	private final static int MAX_SIZE = Integer.MAX_VALUE;
    
    
    @Resource(name = "checkBcdlOrderTaskThread")
    private CheckOrderTaskThread checkOrderTaskThread;
    
    @Resource(name = "bankOrderQueryManager")
    private BankOrderQueryManager bankOrderQuery;

    /**
     * 银行流水状态
     */
    private String orderStatus;

    /**
     * 对单次数
     */
    private int totalCheckTimes;

    /**
     * 任务执行
     */
    public void doTask() {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(4, 10, 3, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(100), new ThreadPoolExecutor.CallerRunsPolicy());

        try{
	        int pageSize = 100;
	        int pageIndex = 1;
	        int count = 0;
	
	        checkBefore();
	        
	        int resCount = getCheckOrderCount(orderStatus, totalCheckTimes);
	
	        List<BankOrder> list = null;
	        while (count < resCount) {
	            list = getCheckOrder(orderStatus, totalCheckTimes, pageIndex, pageSize);
	            if (list == null || list.size() == 0) {
	                logger.error("no bankorder data.");
	            }
	
	            LinkedBlockingQueue<BankOrder> queue = new LinkedBlockingQueue<BankOrder>();
	            queue.addAll(list);
	
	            int size = queue.size();
	            CountDownLatch latch = new CountDownLatch(size);
	
	            checkOrderTaskThread.setLatch(latch);
	            checkOrderTaskThread.setQueue(queue);
	
	            for (int i = 0; i < list.size(); i++) {
	                threadPool.execute(checkOrderTaskThread);
	            }
	
	            count += pageSize;
	            pageIndex++;
	
	            try {
	                latch.await(5, TimeUnit.MINUTES);
	            } catch (InterruptedException e) {
	                logger.error(getClass().getName() + " doTask fail.", e);
	            }
	        }
        } catch (Throwable t) {
			logger.error("执行对单Task时出现异常" ,t);
		} finally {
			ExecutorUtil.gracefulShutdown(threadPool, 1000 * 60 * 3);
		}
    }

    /**
     * 待对账订单笔数
     * @param orderStatus
     * @param totalCheckTimes
     * @return
     */
    private int getCheckOrderCount(String orderStatus, int totalCheckTimes){
    	int resCount = bankOrderQuery.getCheckBcdlOrderCount(orderStatus, totalCheckTimes);
        if (resCount > MAX_SIZE) {
            resCount = MAX_SIZE;
        }
        return resCount;
    }
    
    /**
     * 分页查询对账记录
     * @param orderStatus
     * @param totalCheckTimes
     * @param pageIndex
     * @param pageSize
     * @return
     */
    private List<BankOrder> getCheckOrder(String orderStatus, int totalCheckTimes, int pageIndex, int pageSize){
    	return bankOrderQuery.getCheckBcdlOrder(orderStatus, totalCheckTimes, pageIndex, pageSize);
    }
    
    private void checkBefore() {
    	if(-1 == totalCheckTimes){
    		totalCheckTimes = MAX_SIZE;
    	}
	}
    
    public void setOrderStatus(String orderStatus) {
        this.orderStatus = orderStatus;
    }

    public void setTotalCheckTimes(int totalCheckTimes) {
        this.totalCheckTimes = totalCheckTimes;
    }
}